1 EDA using WDI

1.1 Exploratory Data Analysis, EDA

EDA is an iterative cycle that helps you understand what your data says. When you do EDA, you:

  1. Generate questions about your data

  2. Search for answers by visualising, transforming, and/or modeling your data

  3. Use what you learn to refine your questions and/or generate new questions

EDA is an important part of any data analysis. You can use EDA to make discoveries about the world; or you can use EDA to ensure the quality of your data, asking questions about whether the data meets your standards or not. (Posit Primers: EDA)

1.2 Workflow

  1. Importing data by WDI
df_dataframe_name <- WDI(indicators = c(name1 = "Indicator Code 1", 
name2 = "Indicator Code 2"), extra = TRUE)

Write and read:

write_csv(df_dataframe_name, "data/dataframe_name.csv")
df_dataframe_name <- read_csv("data/dataframe_name.csv")
  1. Viewing data by

head(), str(), summary(), and try df_dataframe_name. See also Environment Tab of RStudio.

  1. Transforming data by restricting the values of a variable.
df_dataframe_name |> filter(var == "value") 
df_dataframe_name |> filter(var %in% c("value_1", ... , "value_n") 
df_dataframe_name |> filter(var != "value") 
df_dataframe_name |> drop_na(var)
  • Creating a new variable by mutation. (A little advanced. PCAP = gdp/pop)
df_dataframe_name |> mutate(var_new = var1 * var2)}
  1. Change orders by arrange()
df_dataframe_name |> arrange(var)
df_dataframe_name |> arrange(dsc(var))
  1. Visualizing using ggplot() + geom_*()

    What type of variation occurs within my variables?

    What type of covariation occurs between my variables?

  • line graph
transformed_data |> ggplot(aes(year, name1)) + geom_line()
transformed_data |> ggplot(aes(year, name2)) + geom_line()
  • scatterplot
transformed_data |> ggplot(aes(name1, name2)) + geom_point()
transformed_data |> ggplot(aes(name1, name2)) + geom_point() + scale_x_log10()
  • scatterplot with a regression line
transformed_data |> ggplot(aes(name1, name2)) + geom_point() +
  geom_smooth(method = "lm", se = FALSE)
transformed_data |> ggplot(aes(name1, name2)) + geom_point() + 
  geom_smooth(method = "lm", se = FALSE) + scale_x_log10()
  • histogram
transformed_data |> ggplot(aes(name1)) + geom_histogram()
  • boxplot

categorical_var: factor(year), income, region

transformed_data |> ggplot(aes(categorical_var, name1)) + geom_boxplot()
  1. Do not forget to add your observations and questions.

1.3 Setup

library(tidyverse)
library(WDI)

2 Examples

2.1 CO2 Emissions Per Capita vs GDP Per Capita

We study the relation between the CO2 emission per capita and the GDP per capita using the following two World Development Indicators.

  1. CO2 emissions (metric tons per capita): EN.ATM.CO2E.PC
  • Description: CO2 emissions (metric tons per capita) Carbon dioxide emissions are those stemming from the burning of fossil fuels and the manufacture of cement. They include carbon dioxide produced during consumption of solid, liquid, and gas fuels and gas flaring. EN.ATM.CO2E.PC
  1. GDP per capita, PPP (constant 2017 international $): NY.GDP.PCAP.PP.KD
  • Description: GDP per capita, PPP (constant 2017 international $) GDP per capita based on purchasing power parity (PPP). PPP GDP is gross domestic product converted to international dollars using purchasing power parity rates. An international dollar has the same purchasing power over GDP as the U.S. dollar has in the United States. GDP at purchaser’s prices is the sum of gross value added by all resident producers in the country plus any product taxes and minus any subsidies not included in the value of the products. It is calculated without making deductions for depreciation of fabricated assets or for depletion and degradation of natural resources. Data are in constant 2017 international dollars. ID: NY.GDP.PCAP.PP.KD

2.1.1 Importing Data

df_co2gdp <- WDI(indicator = c(co2pcap = "EN.ATM.CO2E.PC", gdppcap = "NY.GDP.PCAP.PP.KD"),
                 extra = TRUE)
write_csv(df_co2gdp, "data/co2gdp.csv")
df_co2gdp <- read_csv("data/co2gdp.csv")
Rows: 16758 Columns: 14── Column specification ─────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): country, iso2c, iso3c, region, capital, income, lending
dbl  (5): year, co2pcap, gdppcap, longitude, latitude
lgl  (1): status
date (1): lastupdated
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

2.1.2 Visualization by Line Graphs

2.1.2.1 CO2 per capita

COUNTRY <- "World"
df_co2gdp |> filter(country == COUNTRY) |> drop_na(co2pcap) |>
  ggplot(aes(year, co2pcap)) + geom_line() +
  labs(title = expression(paste(CO[2], " per capita of the World")),
       y = expression(paste(CO[2], " per capita in tons")))

ISO2C <- c("JP", "CN", "ID", "GB", "US", "DE", "FR")
df_co2gdp |> filter(iso2c %in% ISO2C) |> drop_na(co2pcap) |>
  ggplot(aes(year, co2pcap, col = iso2c)) + geom_line() +
  labs(title = expression(paste(CO[2], " per capita of seven conutries with large GDP")),
       subtitle = "China, Germany, France, United Kingdom, India, Japan, United States", 
       y = expression(paste(CO[2], " per capita in tons")))

2.1.2.2 GDP per capita

COUNTRY <- "World"
df_co2gdp |> filter(country == COUNTRY) |> drop_na(gdppcap) |>
  ggplot(aes(year, gdppcap)) + geom_line() +
  labs(title = "GDP per capita of the World")

ISO2C <- c("JP", "CN", "ID", "GB", "US", "DE", "FR")
df_co2gdp |> filter(iso2c %in% ISO2C) |> drop_na(gdppcap) |>
  ggplot(aes(year, gdppcap, col = iso2c)) + geom_line() +
  labs(title = "GDP per capita of seven countries with large GDP",
       subtitle = "China, Germany, France, United Kingdom, India, Japan, United States", 
       y = "GDP per capita PPP",
       caption = "constant 2017 international usd")

2.1.2.3 Ranking of CO2 per capita

df_co2gdp |> filter(year == 2020) |> filter(region != "Aggregates") |>
  drop_na(co2pcap) |> arrange(desc(co2pcap))
df_co2gdp |> filter(year == 2020) |> filter(region != "Aggregates") |>
  drop_na(co2pcap) |> arrange(co2pcap)

Observations and Questions:

  • Top 10 countries of CO2 emission per capita:

    • Qtar, Bahrain, Brunei Darussalam, Kuwait, United Arab Emirates, Oman, Australia, Saudi Arabia, Canada, and United States
  • Lowest 10 countries of CO2 emission per capita:

    • Congo, Dem. Rep., Somalia, Central African Republic, Burundi, Malawi, Niger, Chad, Madagascar, Rwanda, Sierra Leone

2.1.2.4 Ranking of GDP per capita

df_co2gdp |> filter(year == 2020) |> filter(region != "Aggregates") |>
  drop_na(gdppcap) |> arrange(desc(gdppcap))
df_co2gdp |> filter(year == 2020) |> filter(region != "Aggregates") |>
  drop_na(gdppcap) |> arrange(gdppcap)

2.1.3 Histograms and Boxplots for Variation

2.1.3.1 CO2 per capita

INCOME <- c("Low income", "Low & middle income", "Lower middle income", "Middle income", "Upper middle income", "High income")
df_co2gdp |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(co2pcap) |> filter(income != "Not classified") |>
  ggplot(aes(co2pcap, fill = factor(income, levels = INCOME))) + geom_histogram(bins = 15, col = "black", linewidth = 0.1) + 
  scale_x_log10() +
  labs(title = "Histogram of CO2 per capita in 2020", fill = "")

df_co2gdp |> filter(year %in% c(1990, 2000, 2010, 2020)) |> filter(region != "Aggregates") |> 
  drop_na(co2pcap) |> filter(co2pcap > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(co2pcap, fill = factor(year))) + 
  geom_histogram(bins = 15, col = "black", linewidth = 0.1) + 
  scale_x_log10() + facet_wrap(~year) +
  labs(title = "Histogram of CO2 per capita in 1990, 2000, 2010, 2020", fill = "")

df_co2gdp |> filter(year %in% c(1990, 2000, 2010, 2020)) |> filter(region != "Aggregates") |> 
  drop_na(co2pcap) |> filter(co2pcap > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(co2pcap, factor(year), fill = factor(year))) + 
  geom_boxplot() + scale_x_log10() + labs(y = "") + theme(legend.position = "none")

df_co2gdp |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(co2pcap) |> filter(co2pcap > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(co2pcap, factor(income, levels = INCOME), fill = income)) + 
  geom_boxplot() + scale_x_log10() + 
  labs(title = "CO2 per capita by income level", y = "", fill = "") +
  theme(legend.position = "none")

df_co2gdp |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(co2pcap) |> filter(co2pcap > 0) |> 
  ggplot(aes(co2pcap, region, fill = region)) + 
  geom_boxplot() + scale_x_log10() + 
  labs(title = "CO2 per capita by region", y = "", fill = "") +
  theme(legend.position = "none")

2.1.3.2 GDP per capita

df_co2gdp |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(gdppcap) |> filter(income != "Not classified") |>
  ggplot(aes(gdppcap, fill = factor(income, levels = INCOME))) + geom_histogram(bins = 15, col = "black", linewidth = 0.1) + 
  scale_x_log10() +
  labs(title = "Histogram of GDP per capita in 2020", fill = "")

df_co2gdp |> filter(year %in% c(1990, 2000, 2010, 2020)) |> filter(region != "Aggregates") |> 
  drop_na(gdppcap) |> filter(gdppcap > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(gdppcap, fill = factor(year))) + 
  geom_histogram(bins = 15, col = "black", linewidth = 0.1) + 
  scale_x_log10() + facet_wrap(~year) +
  labs(title = "Histogram of GDP per capita in 1990, 2000, 2010, 2020", fill = "") +
  theme(legend.position = "none")

df_co2gdp |> filter(year %in% c(1990, 2000, 2010, 2020)) |> filter(region != "Aggregates") |> 
  drop_na(gdppcap) |> filter(gdppcap > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(gdppcap, factor(year), fill = factor(year))) + 
  geom_boxplot() + scale_x_log10() + labs(y = "") + theme(legend.position = "none")

df_co2gdp |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(gdppcap) |> filter(gdppcap > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(gdppcap, factor(income, levels = INCOME), fill = income)) + 
  geom_boxplot() + scale_x_log10() + 
  labs(title = "GDP per capita by income level", y = "", fill = "") +
  theme(legend.position = "none")

df_co2gdp |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(gdppcap) |> filter(gdppcap > 0) |> 
  ggplot(aes(gdppcap, region, fill = region)) + 
  geom_boxplot() + scale_x_log10() + 
  labs(title = "GDP per capita by region", y = "", fill = "") +
  theme(legend.position = "none")

2.1.4 Scatterplot for Covariation

2.1.4.1 Scatterplot with a regression line

df_co2gdp |> filter(year == 2020) |> 
  drop_na(gdppcap, co2pcap) |>
  ggplot(aes(gdppcap, co2pcap)) + geom_point(aes(col = region)) +
  geom_smooth(method = "lm", formula = 'y~x', se = FALSE) +
  scale_x_log10() + scale_y_log10() +
  labs(title = "GDP per capita vs CO2 per capita",
       x = "GDP per capita",
       y = expression(paste(CO[2], " per capita in tons")))

2.1.4.2 Summary of a linear model

df_co2gdp |> filter(year == 2020) |> drop_na(gdppcap, co2pcap) |>
  lm(log10(co2pcap)~log10(gdppcap), data = _) |> summary()

Call:
lm(formula = log10(co2pcap) ~ log10(gdppcap), data = drop_na(filter(df_co2gdp, 
    year == 2020), gdppcap, co2pcap))

Residuals:
     Min       1Q   Median       3Q      Max 
-0.60778 -0.15660 -0.00651  0.16129  0.59437 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)    -4.31545    0.13386  -32.24   <2e-16 ***
log10(gdppcap)  1.13831    0.03288   34.62   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2362 on 228 degrees of freedom
Multiple R-squared:  0.8402,    Adjusted R-squared:  0.8395 
F-statistic:  1199 on 1 and 228 DF,  p-value: < 2.2e-16

2.2 School Enrollment vs GDP Per Capita

2.2.2 Importing Data

df_sec_ter_gdp <- WDI(indicator = c(sec = "SE.SEC.ENRR", ter = "SE.TER.ENRR", 
                                    gdppcap = "NY.GDP.PCAP.PP.KD"), extra = TRUE)
write_csv(df_secgdp, "data/sec_ter_gdp.csv")
df_secgdp <- read_csv("data/sec_ter_gdp.csv")
Rows: 16758 Columns: 14── Column specification ─────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): country, iso2c, iso3c, region, capital, income, lending
dbl  (5): year, sec, gdppcap, longitude, latitude
lgl  (1): status
date (1): lastupdated
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

2.2.3 Visualization by Line Graphs

COUNTRY <- "World"
df_sec_ter_gdp |> filter(country == COUNTRY) |> drop_na(sec, ter) |>
  ggplot() + geom_line(aes(year, sec), col = "blue") + geom_line(aes(year, ter), col = "red") +
  labs(title = "School enrollment; Secondary and Tertiary", 
       subtitle = "secondary in blue and tertiary in red", y = "")

INCOME <- c("Low income", "Low & middle income", "Lower middle income", "Middle income", "Upper middle income", "High income")
df_sec_ter_gdp |> filter(country %in% INCOME) |> drop_na(sec, ter) |>
  ggplot(aes(linetype = factor(country, levels = INCOME))) + geom_line(aes(year, sec), col = "blue") + geom_line(aes(year, ter), col = "red") + ylim(c(0,110)) +
  labs(title = "School enrollment; Secondary and Tertiary", 
       subtitle = "secondary in blue and tertiary in red", linetype = "Income Levels", y = "")

2.2.4 Scatterplot for Covariation

df_sec_ter_gdp |> filter(year == 2020) |> drop_na(sec, ter, gdppcap) |>
  ggplot() + geom_point(aes(gdppcap, sec), col = "blue") + 
  geom_point(aes(gdppcap, ter), col = "red") +
  labs(title = "School enrollment; Secondary and Tertiary vs GDP per capita", 
       subtitle = "secondary in blue and tertiary in red", y = "")

df_sec_ter_gdp |> filter(year == 2020) |> drop_na(sec, ter, gdppcap) |>
  ggplot() + geom_point(aes(gdppcap, sec), col = "blue") + 
  geom_point(aes(gdppcap, ter), col = "red") + 
  scale_x_log10() +
  labs(title = "School enrollment; Secondary and Tertiary vs GDP per capita in log10 scale", 
       subtitle = "secondary in blue and tertiary in red", y = "")

df_sec_ter_gdp |> filter(year == 2020) |> drop_na(sec, ter, gdppcap) |>
  ggplot() + geom_point(aes(gdppcap, sec), col = "blue") + 
  geom_point(aes(gdppcap, ter), col = "red") +
  geom_smooth(aes(gdppcap, sec), col = "blue", method = "lm", formula = 'y~x', se = FALSE) +
  geom_smooth(aes(gdppcap, ter), col = "red", method = "lm", formula = 'y~x', se = FALSE) +
  scale_x_log10() +
  labs(title = "School enrollment; Secondary and Tertiary vs GDP per capita in log10 scale", 
       subtitle = "secondary in blue and tertiary in red with regression lines", y = "")

df_sec_ter_gdp |> filter(year == 2020) |> drop_na(gdppcap, sec) |>
  lm(sec~log10(gdppcap), data = _) |> summary()

Call:
lm(formula = sec ~ log10(gdppcap), data = drop_na(filter(df_sec_ter_gdp, 
    year == 2020), gdppcap, sec))

Residuals:
    Min      1Q  Median      3Q     Max 
-53.777 -10.846  -1.173   9.006  66.996 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)    -102.994     11.933  -8.631 6.38e-15 ***
log10(gdppcap)   46.088      2.841  16.222  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 15.64 on 157 degrees of freedom
Multiple R-squared:  0.6263,    Adjusted R-squared:  0.624 
F-statistic: 263.2 on 1 and 157 DF,  p-value: < 2.2e-16
df_sec_ter_gdp |> filter(year == 2020) |> drop_na(gdppcap, ter) |>
  lm(ter~log10(gdppcap), data = _) |> summary()

Call:
lm(formula = ter ~ log10(gdppcap), data = drop_na(filter(df_sec_ter_gdp, 
    year == 2020), gdppcap, ter))

Residuals:
    Min      1Q  Median      3Q     Max 
-72.696  -8.388  -0.808   8.589  89.657 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)    -159.817     13.877  -11.52   <2e-16 ***
log10(gdppcap)   49.861      3.303   15.09   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 19.18 on 157 degrees of freedom
Multiple R-squared:  0.592, Adjusted R-squared:  0.5894 
F-statistic: 227.8 on 1 and 157 DF,  p-value: < 2.2e-16
df_sec_ter_gdp |> filter(year == 2020, region != "Aggregates") |> drop_na(sec, region) |>
  ggplot(aes(sec, region, fill = region)) + geom_boxplot() + 
  labs(x = "School enrollment, secondary (% gross)", y = "") + theme(legend.position = "none")

df_sec_ter_gdp |> filter(year == 2020, income !="Aggregates") |> drop_na(sec, income) |>
  ggplot(aes(sec, factor(income, levels = INCOME), fill = income)) + geom_boxplot() + 
  labs(title = "Seconary education: School enrollment by income level", x = "School enrollment, secondary (% gross)", y = "") + theme(legend.position = "none")

df_sec_ter_gdp |> filter(year == 2020, region != "Aggregates") |> drop_na(ter, region) |>
  ggplot(aes(ter, region, fill = region)) + geom_boxplot() + 
  labs(x = "School enrollment, tertiary (% gross)", y = "") + theme(legend.position = "none")

df_sec_ter_gdp |> filter(year == 2020, income != "Aggregates") |> drop_na(ter, income) |>
  ggplot(aes(ter, factor(income, levels = INCOME), fill = income)) + geom_boxplot() + 
  labs(title = "Tertiary education: School enrollment by income level", x = "School enrollment, tertiary (% gross)", y = "") + theme(legend.position = "none")

Observations

  • Income level has more effect on school enrollment to tertiary education

3 Your Project

3.1 Title of your project

We study …..

  1. Name of the indicator 1: Indicator Code 1
  • Description:
  1. Name of the indicator 2: Indicator Code 2
  • Description:

3.1.1 Importing Data

Edit the following code chunk!
chosen_indicator_1 <- "EN.ATM.CO2E.PC"
short_name_1 <- "co2pcap"
chosen_indicator_2 <- "NY.GDP.PCAP.PP.KD"
short_name_2 <- "gdppcap"
df_yourdata <- WDI(indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2),
                 extra = TRUE)
write_csv(df_yourdata, "data/yourdata.csv")
df_yourdata <- read_csv("data/yourdata.csv")
Rows: 16758 Columns: 14── Column specification ─────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): country, iso2c, iso3c, region, capital, income, lending
dbl  (5): year, short_name_1, short_name_2, longitude, latitude
lgl  (1): status
date (1): lastupdated
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

3.1.2 Visualization by Line Graphs

3.1.2.1 Name of the Indicator 1

Edit the title and the label of y-axis.
COUNTRY <- "World"
df_yourdata |> filter(country == COUNTRY) |> drop_na(short_name_1) |>
  ggplot(aes(year, short_name_1)) + geom_line() +
  labs(title = "",
       y = "")

Observations and Questions:

Edit ISO2C, title, subtitle, and the label of y-axis.
ISO2C <- c("JP", "CN", "ID", "GB", "US", "DE", "FR")
df_yourdata |> filter(iso2c %in% ISO2C) |> drop_na(short_name_1) |>
  ggplot(aes(year, short_name_1, col = iso2c)) + geom_line() +
  labs(title = "",
       subtitle = "China, Germany, France, United Kingdom, India, Japan, United States", 
       y = "")

Observations and Questions:

3.1.2.2 Name of the Indicator 2

Edit COUNTRY and the title.
COUNTRY <- "World"
df_yourdata |> filter(country == COUNTRY) |> drop_na(short_name_2) |>
  ggplot(aes(year, short_name_2)) + geom_line() +
  labs(title = "")

Observations and Questions:

Edit ISO2C, title, subtitle, and the label of y-axis, and add caption if preferable.
ISO2C <- c("JP", "CN", "ID", "GB", "US", "DE", "FR")
df_yourdata |> filter(iso2c %in% ISO2C) |> drop_na(short_name_2) |>
  ggplot(aes(year, short_name_2, col = iso2c)) + geom_line() +
  labs(title = "",
       subtitle = "China, Germany, France, United Kingdom, India, Japan, United States", 
       y = "",
       caption = "")

Observations and Questions:

3.1.2.3 Ranking of the indicator 1

Edit year if necessary.
df_yourdata |> filter(year == 2020) |> filter(region != "Aggregates") |>
  drop_na(short_name_1) |> arrange(desc(short_name_1))
df_yourdata |> filter(year == 2020) |> filter(region != "Aggregates") |>
  drop_na(short_name_1) |> arrange(short_name_1)

Observations and Questions:

3.1.2.4 Ranking of the Indicator 2

df_yourdata |> filter(year == 2020) |> filter(region != "Aggregates") |>
  drop_na(short_name_2) |> arrange(desc(short_name_2))

Observations and Questions:

df_yourdata |> filter(year == 2020) |> filter(region != "Aggregates") |>
  drop_na(short_name_2) |> arrange(short_name_2)

Observations and Questions:

3.1.3 Histograms and Boxplots for Variation

3.1.3.1 Name of the Indicator 1

Edit the title and year.
df_yourdata |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(short_name_1) |> filter(income != "Not classified") |>
  ggplot(aes(short_name_1, fill = factor(income, levels = INCOME))) + geom_histogram(bins = 15, col = "black", linewidth = 0.1) + 
  scale_x_log10() +
  labs(title = "", fill = "")

Observations and Questions:

Edit the title and the years.
df_yourdata |> filter(year %in% c(1990, 2000, 2010, 2020)) |> filter(region != "Aggregates") |> 
  drop_na(short_name_1) |> filter(short_name_1 > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(short_name_1, fill = factor(year))) + 
  geom_histogram(bins = 15, col = "black", linewidth = 0.1) + 
  scale_x_log10() + facet_wrap(~year) +
  labs(title = "", fill = "")

Observations and Questions:

df_yourdata |> filter(year %in% c(1990, 2000, 2010, 2020)) |> filter(region != "Aggregates") |> 
  drop_na(short_name_1) |> filter(short_name_1 > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(short_name_1, factor(year), fill = factor(year))) + 
  geom_boxplot() + scale_x_log10() + labs(y = "") + theme(legend.position = "none")

Observations and Questions:

Edit the title, and the year if necessary.
df_yourdata |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(short_name_1) |> filter(short_name_1 > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(short_name_1, factor(income, levels = INCOME), fill = income)) + 
  geom_boxplot() + scale_x_log10() + 
  labs(title = "", y = "", fill = "") +
  theme(legend.position = "none")

Observations and Questions:

Edit the title and year if necessary.
df_yourdata |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(short_name_1) |> filter(short_name_1 > 0) |> 
  ggplot(aes(short_name_1, region, fill = region)) + 
  geom_boxplot() + scale_x_log10() + 
  labs(title = "", y = "", fill = "") +
  theme(legend.position = "none")

Observations and Questions:

3.1.3.2 GDP per capita

Edit the title, and year if necessary.
df_yourdata |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(short_name_2) |> filter(income != "Not classified") |>
  ggplot(aes(short_name_2, fill = factor(income, levels = INCOME))) + geom_histogram(bins = 15, col = "black", linewidth = 0.1) + 
  scale_x_log10() +
  labs(title = "", fill = "")

Edit the title and the year if necessary.
df_yourdata |> filter(year %in% c(1990, 2000, 2010, 2020)) |> filter(region != "Aggregates") |> 
  drop_na(short_name_2) |> filter(short_name_2 > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(short_name_2, fill = factor(year))) + 
  geom_histogram(bins = 15, col = "black", linewidth = 0.1) + 
  scale_x_log10() + facet_wrap(~year) +
  labs(title = "", fill = "") +
  theme(legend.position = "none")

Observations and Questions:

df_yourdata |> filter(year %in% c(1990, 2000, 2010, 2020)) |> filter(region != "Aggregates") |> 
  drop_na(short_name_2) |> filter(short_name_2 > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(short_name_2, factor(year), fill = factor(year))) + 
  geom_boxplot() + scale_x_log10() + labs(y = "") + theme(legend.position = "none")

Observations and Questions:

Edit the title, and the year if necessary.
df_yourdata |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(short_name_2) |> filter(short_name_2 > 0) |> filter(income != "Not classified") |> 
  ggplot(aes(short_name_2, factor(income, levels = INCOME), fill = income)) + 
  geom_boxplot() + scale_x_log10() + 
  labs(title = "", y = "", fill = "") +
  theme(legend.position = "none")

Observations and Questions:

Edit the title and the year if necessary.
df_yourdata |> filter(year == 2020) |> filter(region != "Aggregates") |> 
  drop_na(short_name_2) |> filter(short_name_2 > 0) |> 
  ggplot(aes(short_name_2, region, fill = region)) + 
  geom_boxplot() + scale_x_log10() + 
  labs(title = "", y = "", fill = "") +
  theme(legend.position = "none")

3.1.4 Scatterplot for Covariation

3.1.4.1 Scatterplot with a regression line

Edit the title, the labels of x- and y- axes.
df_yourdata |> filter(year == 2020) |> 
  drop_na(short_name_2, short_name_1) |>
  ggplot(aes(short_name_2, short_name_1)) + geom_point(aes(col = region)) +
  geom_smooth(method = "lm", formula = 'y~x', se = FALSE) +
  scale_x_log10() + scale_y_log10() +
  labs(title = "",
       x = "",
       y = "")

Observations and Questions:

3.1.4.2 Summary of a linear model

Edit year if necessary.
df_yourdata |> filter(year == 2020) |> drop_na(short_name_2, short_name_1) |>
  lm(log10(short_name_1)~log10(short_name_2), data = _) |> summary()

Call:
lm(formula = log10(short_name_1) ~ log10(short_name_2), data = drop_na(filter(df_yourdata, 
    year == 2020), short_name_2, short_name_1))

Residuals:
     Min       1Q   Median       3Q      Max 
-0.60778 -0.15660 -0.00651  0.16129  0.59437 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)         -4.31545    0.13386  -32.24   <2e-16 ***
log10(short_name_2)  1.13831    0.03288   34.62   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2362 on 228 degrees of freedom
Multiple R-squared:  0.8402,    Adjusted R-squared:  0.8395 
F-statistic:  1199 on 1 and 228 DF,  p-value: < 2.2e-16

Observations and Questions:

LS0tCnRpdGxlOiAiV0RJIFRlbXBsYXRlIgphdXRob3I6ICJJRCBMYXN0LCBGaXJzdCIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgcmVmZXJlbmNlX2RvY3g6IGludHJvMndkaV90bXAuZG9jeAogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCi0tLQoKIyBFREEgdXNpbmcgV0RJCgojIyBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzLCBFREEKCkVEQSBpcyBhbiBpdGVyYXRpdmUgY3ljbGUgdGhhdCBoZWxwcyB5b3UgdW5kZXJzdGFuZCB3aGF0IHlvdXIgZGF0YSBzYXlzLiBXaGVuIHlvdSBkbyBFREEsIHlvdToKCjEuICBHZW5lcmF0ZSBxdWVzdGlvbnMgYWJvdXQgeW91ciBkYXRhCgoyLiAgU2VhcmNoIGZvciBhbnN3ZXJzIGJ5IHZpc3VhbGlzaW5nLCB0cmFuc2Zvcm1pbmcsIGFuZC9vciBtb2RlbGluZyB5b3VyIGRhdGEKCjMuICBVc2Ugd2hhdCB5b3UgbGVhcm4gdG8gcmVmaW5lIHlvdXIgcXVlc3Rpb25zIGFuZC9vciBnZW5lcmF0ZSBuZXcgcXVlc3Rpb25zCgpFREEgaXMgYW4gaW1wb3J0YW50IHBhcnQgb2YgYW55IGRhdGEgYW5hbHlzaXMuIFlvdSBjYW4gdXNlIEVEQSB0byBtYWtlIGRpc2NvdmVyaWVzIGFib3V0IHRoZSB3b3JsZDsgb3IgeW91IGNhbiB1c2UgRURBIHRvIGVuc3VyZSB0aGUgcXVhbGl0eSBvZiB5b3VyIGRhdGEsIGFza2luZyBxdWVzdGlvbnMgYWJvdXQgd2hldGhlciB0aGUgZGF0YSBtZWV0cyB5b3VyIHN0YW5kYXJkcyBvciBub3QuIChQb3NpdCBQcmltZXJzOiBbRURBXShodHRwczovL3Bvc2l0LmNsb3VkL2xlYXJuL3ByaW1lcnMvMy4xKSkKCiMjIFdvcmtmbG93CgoxLiAgSW1wb3J0aW5nIGRhdGEgYnkgV0RJCgpgYGAgICAgICAgICAKZGZfZGF0YWZyYW1lX25hbWUgPC0gV0RJKGluZGljYXRvcnMgPSBjKG5hbWUxID0gIkluZGljYXRvciBDb2RlIDEiLCAKbmFtZTIgPSAiSW5kaWNhdG9yIENvZGUgMiIpLCBleHRyYSA9IFRSVUUpCmBgYAoKV3JpdGUgYW5kIHJlYWQ6CgpgYGAgICAgICAgICAKd3JpdGVfY3N2KGRmX2RhdGFmcmFtZV9uYW1lLCAiZGF0YS9kYXRhZnJhbWVfbmFtZS5jc3YiKQpkZl9kYXRhZnJhbWVfbmFtZSA8LSByZWFkX2NzdigiZGF0YS9kYXRhZnJhbWVfbmFtZS5jc3YiKQpgYGAKCjIuICBWaWV3aW5nIGRhdGEgYnkKCmBoZWFkKClgLCBgc3RyKClgLCBgc3VtbWFyeSgpYCwgYW5kIHRyeSBgZGZfZGF0YWZyYW1lX25hbWVgLiBTZWUgYWxzbyBFbnZpcm9ubWVudCBUYWIgb2YgUlN0dWRpby4KCjMuICBUcmFuc2Zvcm1pbmcgZGF0YSBieSByZXN0cmljdGluZyB0aGUgdmFsdWVzIG9mIGEgdmFyaWFibGUuCgpgYGAgICAgICAgICAKZGZfZGF0YWZyYW1lX25hbWUgfD4gZmlsdGVyKHZhciA9PSAidmFsdWUiKSAKZGZfZGF0YWZyYW1lX25hbWUgfD4gZmlsdGVyKHZhciAlaW4lIGMoInZhbHVlXzEiLCAuLi4gLCAidmFsdWVfbiIpIApkZl9kYXRhZnJhbWVfbmFtZSB8PiBmaWx0ZXIodmFyICE9ICJ2YWx1ZSIpIApkZl9kYXRhZnJhbWVfbmFtZSB8PiBkcm9wX25hKHZhcikKYGBgCgotICAgQ3JlYXRpbmcgYSBuZXcgdmFyaWFibGUgYnkgbXV0YXRpb24uIChBIGxpdHRsZSBhZHZhbmNlZC4gUENBUCA9IGdkcC9wb3ApCgpgYGAgICAgICAgICAKZGZfZGF0YWZyYW1lX25hbWUgfD4gbXV0YXRlKHZhcl9uZXcgPSB2YXIxICogdmFyMil9CmBgYAoKNC4gIENoYW5nZSBvcmRlcnMgYnkgYGFycmFuZ2UoKWAKCmBgYCAgICAgICAgIApkZl9kYXRhZnJhbWVfbmFtZSB8PiBhcnJhbmdlKHZhcikKZGZfZGF0YWZyYW1lX25hbWUgfD4gYXJyYW5nZShkc2ModmFyKSkKYGBgCgo1LiAgVmlzdWFsaXppbmcgdXNpbmcgZ2dwbG90KCkgKyBnZW9tXF9cKigpCgogICAgV2hhdCB0eXBlIG9mwqAqKnZhcmlhdGlvbioqwqBvY2N1cnPCoCoqd2l0aGluKirCoG15IHZhcmlhYmxlcz8KCiAgICBXaGF0IHR5cGUgb2bCoCoqY292YXJpYXRpb24qKsKgb2NjdXJzwqAqKmJldHdlZW4qKsKgbXkgdmFyaWFibGVzPwoKLSAgIGxpbmUgZ3JhcGgKCmBgYCAgICAgICAgIAp0cmFuc2Zvcm1lZF9kYXRhIHw+IGdncGxvdChhZXMoeWVhciwgbmFtZTEpKSArIGdlb21fbGluZSgpCnRyYW5zZm9ybWVkX2RhdGEgfD4gZ2dwbG90KGFlcyh5ZWFyLCBuYW1lMikpICsgZ2VvbV9saW5lKCkKYGBgCgotICAgc2NhdHRlcnBsb3QKCmBgYCAgICAgICAgIAp0cmFuc2Zvcm1lZF9kYXRhIHw+IGdncGxvdChhZXMobmFtZTEsIG5hbWUyKSkgKyBnZW9tX3BvaW50KCkKdHJhbnNmb3JtZWRfZGF0YSB8PiBnZ3Bsb3QoYWVzKG5hbWUxLCBuYW1lMikpICsgZ2VvbV9wb2ludCgpICsgc2NhbGVfeF9sb2cxMCgpCmBgYAoKLSAgIHNjYXR0ZXJwbG90IHdpdGggYSByZWdyZXNzaW9uIGxpbmUKCmBgYCAgICAgICAgIAp0cmFuc2Zvcm1lZF9kYXRhIHw+IGdncGxvdChhZXMobmFtZTEsIG5hbWUyKSkgKyBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpCnRyYW5zZm9ybWVkX2RhdGEgfD4gZ2dwbG90KGFlcyhuYW1lMSwgbmFtZTIpKSArIGdlb21fcG9pbnQoKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsgc2NhbGVfeF9sb2cxMCgpCmBgYAoKLSAgIGhpc3RvZ3JhbQoKCmBgYCAgICAgICAgIAp0cmFuc2Zvcm1lZF9kYXRhIHw+IGdncGxvdChhZXMobmFtZTEpKSArIGdlb21faGlzdG9ncmFtKCkKYGBgCgotICAgYm94cGxvdAoKYGNhdGVnb3JpY2FsX3ZhcmA6IGBmYWN0b3IoeWVhcilgLCBgaW5jb21lYCwgYHJlZ2lvbmAKCmBgYCAgICAgICAgIAp0cmFuc2Zvcm1lZF9kYXRhIHw+IGdncGxvdChhZXMoY2F0ZWdvcmljYWxfdmFyLCBuYW1lMSkpICsgZ2VvbV9ib3hwbG90KCkKYGBgCgo2LiAgRG8gbm90IGZvcmdldCB0byBhZGQgeW91ciBvYnNlcnZhdGlvbnMgYW5kIHF1ZXN0aW9ucy4KCiMjIFNldHVwCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoV0RJKQpgYGAKCiMgRXhhbXBsZXMKCiMjIENPfjJ+IEVtaXNzaW9ucyBQZXIgQ2FwaXRhIHZzIEdEUCBQZXIgQ2FwaXRhCgpXZSBzdHVkeSB0aGUgcmVsYXRpb24gYmV0d2VlbiB0aGUgQ09+Mn4gZW1pc3Npb24gcGVyIGNhcGl0YSBhbmQgdGhlIEdEUCBwZXIgY2FwaXRhIHVzaW5nIHRoZSBmb2xsb3dpbmcgdHdvIFdvcmxkIERldmVsb3BtZW50IEluZGljYXRvcnMuCgoxLiAgQ08yIGVtaXNzaW9ucyAobWV0cmljIHRvbnMgcGVyIGNhcGl0YSk6IEVOLkFUTS5DTzJFLlBDCgotICAgRGVzY3JpcHRpb246IENPMiBlbWlzc2lvbnMgKG1ldHJpYyB0b25zIHBlciBjYXBpdGEpIENhcmJvbiBkaW94aWRlIGVtaXNzaW9ucyBhcmUgdGhvc2Ugc3RlbW1pbmcgZnJvbSB0aGUgYnVybmluZyBvZiBmb3NzaWwgZnVlbHMgYW5kIHRoZSBtYW51ZmFjdHVyZSBvZiBjZW1lbnQuIFRoZXkgaW5jbHVkZSBjYXJib24gZGlveGlkZSBwcm9kdWNlZCBkdXJpbmcgY29uc3VtcHRpb24gb2Ygc29saWQsIGxpcXVpZCwgYW5kIGdhcyBmdWVscyBhbmQgZ2FzIGZsYXJpbmcuIEVOLkFUTS5DTzJFLlBDCgoyLiAgR0RQIHBlciBjYXBpdGEsIFBQUCAoY29uc3RhbnQgMjAxNyBpbnRlcm5hdGlvbmFsIFwkKTogTlkuR0RQLlBDQVAuUFAuS0QKCi0gICBEZXNjcmlwdGlvbjogR0RQIHBlciBjYXBpdGEsIFBQUCAoY29uc3RhbnQgMjAxNyBpbnRlcm5hdGlvbmFsIFwkKSBHRFAgcGVyIGNhcGl0YSBiYXNlZCBvbiBwdXJjaGFzaW5nIHBvd2VyIHBhcml0eSAoUFBQKS4gUFBQIEdEUCBpcyBncm9zcyBkb21lc3RpYyBwcm9kdWN0IGNvbnZlcnRlZCB0byBpbnRlcm5hdGlvbmFsIGRvbGxhcnMgdXNpbmcgcHVyY2hhc2luZyBwb3dlciBwYXJpdHkgcmF0ZXMuIEFuIGludGVybmF0aW9uYWwgZG9sbGFyIGhhcyB0aGUgc2FtZSBwdXJjaGFzaW5nIHBvd2VyIG92ZXIgR0RQIGFzIHRoZSBVLlMuIGRvbGxhciBoYXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMuIEdEUCBhdCBwdXJjaGFzZXIncyBwcmljZXMgaXMgdGhlIHN1bSBvZiBncm9zcyB2YWx1ZSBhZGRlZCBieSBhbGwgcmVzaWRlbnQgcHJvZHVjZXJzIGluIHRoZSBjb3VudHJ5IHBsdXMgYW55IHByb2R1Y3QgdGF4ZXMgYW5kIG1pbnVzIGFueSBzdWJzaWRpZXMgbm90IGluY2x1ZGVkIGluIHRoZSB2YWx1ZSBvZiB0aGUgcHJvZHVjdHMuIEl0IGlzIGNhbGN1bGF0ZWQgd2l0aG91dCBtYWtpbmcgZGVkdWN0aW9ucyBmb3IgZGVwcmVjaWF0aW9uIG9mIGZhYnJpY2F0ZWQgYXNzZXRzIG9yIGZvciBkZXBsZXRpb24gYW5kIGRlZ3JhZGF0aW9uIG9mIG5hdHVyYWwgcmVzb3VyY2VzLiBEYXRhIGFyZSBpbiBjb25zdGFudCAyMDE3IGludGVybmF0aW9uYWwgZG9sbGFycy4gSUQ6IE5ZLkdEUC5QQ0FQLlBQLktECgojIyMgSW1wb3J0aW5nIERhdGEKCmBgYHtyIGNhY2hlID0gVFJVRSwgZXZhbCA9IEZBTFNFfQpkZl9jbzJnZHAgPC0gV0RJKGluZGljYXRvciA9IGMoY28ycGNhcCA9ICJFTi5BVE0uQ08yRS5QQyIsIGdkcHBjYXAgPSAiTlkuR0RQLlBDQVAuUFAuS0QiKSwKICAgICAgICAgICAgICAgICBleHRyYSA9IFRSVUUpCmBgYAoKYGBge3IgZXZhbCA9IEZBTFNFfQp3cml0ZV9jc3YoZGZfY28yZ2RwLCAiZGF0YS9jbzJnZHAuY3N2IikKYGBgCgpgYGB7cn0KZGZfY28yZ2RwIDwtIHJlYWRfY3N2KCJkYXRhL2NvMmdkcC5jc3YiKQpgYGAKCiMjIyBWaXN1YWxpemF0aW9uIGJ5IExpbmUgR3JhcGhzCgojIyMjIENPfjJ+IHBlciBjYXBpdGEKCmBgYHtyfQpDT1VOVFJZIDwtICJXb3JsZCIKZGZfY28yZ2RwIHw+IGZpbHRlcihjb3VudHJ5ID09IENPVU5UUlkpIHw+IGRyb3BfbmEoY28ycGNhcCkgfD4KICBnZ3Bsb3QoYWVzKHllYXIsIGNvMnBjYXApKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihwYXN0ZShDT1syXSwgIiBwZXIgY2FwaXRhIG9mIHRoZSBXb3JsZCIpKSwKICAgICAgIHkgPSBleHByZXNzaW9uKHBhc3RlKENPWzJdLCAiIHBlciBjYXBpdGEgaW4gdG9ucyIpKSkKYGBgCgpgYGB7cn0KSVNPMkMgPC0gYygiSlAiLCAiQ04iLCAiSUQiLCAiR0IiLCAiVVMiLCAiREUiLCAiRlIiKQpkZl9jbzJnZHAgfD4gZmlsdGVyKGlzbzJjICVpbiUgSVNPMkMpIHw+IGRyb3BfbmEoY28ycGNhcCkgfD4KICBnZ3Bsb3QoYWVzKHllYXIsIGNvMnBjYXAsIGNvbCA9IGlzbzJjKSkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24ocGFzdGUoQ09bMl0sICIgcGVyIGNhcGl0YSBvZiBzZXZlbiBjb251dHJpZXMgd2l0aCBsYXJnZSBHRFAiKSksCiAgICAgICBzdWJ0aXRsZSA9ICJDaGluYSwgR2VybWFueSwgRnJhbmNlLCBVbml0ZWQgS2luZ2RvbSwgSW5kaWEsIEphcGFuLCBVbml0ZWQgU3RhdGVzIiwgCiAgICAgICB5ID0gZXhwcmVzc2lvbihwYXN0ZShDT1syXSwgIiBwZXIgY2FwaXRhIGluIHRvbnMiKSkpCmBgYAoKIyMjIyBHRFAgcGVyIGNhcGl0YQoKYGBge3J9CkNPVU5UUlkgPC0gIldvcmxkIgpkZl9jbzJnZHAgfD4gZmlsdGVyKGNvdW50cnkgPT0gQ09VTlRSWSkgfD4gZHJvcF9uYShnZHBwY2FwKSB8PgogIGdncGxvdChhZXMoeWVhciwgZ2RwcGNhcCkpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiR0RQIHBlciBjYXBpdGEgb2YgdGhlIFdvcmxkIikKYGBgCgpgYGB7cn0KSVNPMkMgPC0gYygiSlAiLCAiQ04iLCAiSUQiLCAiR0IiLCAiVVMiLCAiREUiLCAiRlIiKQpkZl9jbzJnZHAgfD4gZmlsdGVyKGlzbzJjICVpbiUgSVNPMkMpIHw+IGRyb3BfbmEoZ2RwcGNhcCkgfD4KICBnZ3Bsb3QoYWVzKHllYXIsIGdkcHBjYXAsIGNvbCA9IGlzbzJjKSkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9ICJHRFAgcGVyIGNhcGl0YSBvZiBzZXZlbiBjb3VudHJpZXMgd2l0aCBsYXJnZSBHRFAiLAogICAgICAgc3VidGl0bGUgPSAiQ2hpbmEsIEdlcm1hbnksIEZyYW5jZSwgVW5pdGVkIEtpbmdkb20sIEluZGlhLCBKYXBhbiwgVW5pdGVkIFN0YXRlcyIsIAogICAgICAgeSA9ICJHRFAgcGVyIGNhcGl0YSBQUFAiLAogICAgICAgY2FwdGlvbiA9ICJjb25zdGFudCAyMDE3IGludGVybmF0aW9uYWwgdXNkIikKYGBgCgojIyMjIFJhbmtpbmcgb2YgQ09+Mn4gcGVyIGNhcGl0YQoKYGBge3J9CmRmX2NvMmdkcCB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwKSB8PiBmaWx0ZXIocmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4KICBkcm9wX25hKGNvMnBjYXApIHw+IGFycmFuZ2UoZGVzYyhjbzJwY2FwKSkKYGBgCgpgYGB7cn0KZGZfY28yZ2RwIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PgogIGRyb3BfbmEoY28ycGNhcCkgfD4gYXJyYW5nZShjbzJwY2FwKQpgYGAKCioqT2JzZXJ2YXRpb25zIGFuZCBRdWVzdGlvbnM6KioKCi0gICBUb3AgMTAgY291bnRyaWVzIG9mIENPfjJ+IGVtaXNzaW9uIHBlciBjYXBpdGE6CgogICAgLSAgIFF0YXIsIEJhaHJhaW4sIEJydW5laSBEYXJ1c3NhbGFtLCBLdXdhaXQsIFVuaXRlZCBBcmFiIEVtaXJhdGVzLCBPbWFuLCBBdXN0cmFsaWEsIFNhdWRpIEFyYWJpYSwgQ2FuYWRhLCBhbmQgVW5pdGVkIFN0YXRlcwoKLSAgIExvd2VzdCAxMCBjb3VudHJpZXMgb2YgQ09+Mn4gZW1pc3Npb24gcGVyIGNhcGl0YToKCiAgICAtICAgQ29uZ28sIERlbS4gUmVwLiwgU29tYWxpYSwgQ2VudHJhbCBBZnJpY2FuIFJlcHVibGljLCBCdXJ1bmRpLCBNYWxhd2ksIE5pZ2VyLCBDaGFkLCBNYWRhZ2FzY2FyLCBSd2FuZGEsIFNpZXJyYSBMZW9uZQoKIyMjIyBSYW5raW5nIG9mIEdEUCBwZXIgY2FwaXRhCgpgYGB7cn0KZGZfY28yZ2RwIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PgogIGRyb3BfbmEoZ2RwcGNhcCkgfD4gYXJyYW5nZShkZXNjKGdkcHBjYXApKQpgYGAKCmBgYHtyfQpkZl9jbzJnZHAgfD4gZmlsdGVyKHllYXIgPT0gMjAyMCkgfD4gZmlsdGVyKHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+CiAgZHJvcF9uYShnZHBwY2FwKSB8PiBhcnJhbmdlKGdkcHBjYXApCmBgYAoKIyMjIEhpc3RvZ3JhbXMgYW5kIEJveHBsb3RzIGZvciBWYXJpYXRpb24KCiMjIyMgQ09+Mn4gcGVyIGNhcGl0YQoKYGBge3J9CklOQ09NRSA8LSBjKCJMb3cgaW5jb21lIiwgIkxvdyAmIG1pZGRsZSBpbmNvbWUiLCAiTG93ZXIgbWlkZGxlIGluY29tZSIsICJNaWRkbGUgaW5jb21lIiwgIlVwcGVyIG1pZGRsZSBpbmNvbWUiLCAiSGlnaCBpbmNvbWUiKQpkZl9jbzJnZHAgfD4gZmlsdGVyKHllYXIgPT0gMjAyMCkgfD4gZmlsdGVyKHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoY28ycGNhcCkgfD4gZmlsdGVyKGluY29tZSAhPSAiTm90IGNsYXNzaWZpZWQiKSB8PgogIGdncGxvdChhZXMoY28ycGNhcCwgZmlsbCA9IGZhY3RvcihpbmNvbWUsIGxldmVscyA9IElOQ09NRSkpKSArIGdlb21faGlzdG9ncmFtKGJpbnMgPSAxNSwgY29sID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC4xKSArIAogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gb2YgQ08yIHBlciBjYXBpdGEgaW4gMjAyMCIsIGZpbGwgPSAiIikKYGBgCgpgYGB7cn0KZGZfY28yZ2RwIHw+IGZpbHRlcih5ZWFyICVpbiUgYygxOTkwLCAyMDAwLCAyMDEwLCAyMDIwKSkgfD4gZmlsdGVyKHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoY28ycGNhcCkgfD4gZmlsdGVyKGNvMnBjYXAgPiAwKSB8PiBmaWx0ZXIoaW5jb21lICE9ICJOb3QgY2xhc3NpZmllZCIpIHw+IAogIGdncGxvdChhZXMoY28ycGNhcCwgZmlsbCA9IGZhY3Rvcih5ZWFyKSkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDE1LCBjb2wgPSAiYmxhY2siLCBsaW5ld2lkdGggPSAwLjEpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsgZmFjZXRfd3JhcCh+eWVhcikgKwogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtIG9mIENPMiBwZXIgY2FwaXRhIGluIDE5OTAsIDIwMDAsIDIwMTAsIDIwMjAiLCBmaWxsID0gIiIpCmBgYAoKYGBge3J9CmRmX2NvMmdkcCB8PiBmaWx0ZXIoeWVhciAlaW4lIGMoMTk5MCwgMjAwMCwgMjAxMCwgMjAyMCkpIHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PiAKICBkcm9wX25hKGNvMnBjYXApIHw+IGZpbHRlcihjbzJwY2FwID4gMCkgfD4gZmlsdGVyKGluY29tZSAhPSAiTm90IGNsYXNzaWZpZWQiKSB8PiAKICBnZ3Bsb3QoYWVzKGNvMnBjYXAsIGZhY3Rvcih5ZWFyKSwgZmlsbCA9IGZhY3Rvcih5ZWFyKSkpICsgCiAgZ2VvbV9ib3hwbG90KCkgKyBzY2FsZV94X2xvZzEwKCkgKyBsYWJzKHkgPSAiIikgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKYGBge3J9CmRmX2NvMmdkcCB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwKSB8PiBmaWx0ZXIocmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4gCiAgZHJvcF9uYShjbzJwY2FwKSB8PiBmaWx0ZXIoY28ycGNhcCA+IDApIHw+IGZpbHRlcihpbmNvbWUgIT0gIk5vdCBjbGFzc2lmaWVkIikgfD4gCiAgZ2dwbG90KGFlcyhjbzJwY2FwLCBmYWN0b3IoaW5jb21lLCBsZXZlbHMgPSBJTkNPTUUpLCBmaWxsID0gaW5jb21lKSkgKyAKICBnZW9tX2JveHBsb3QoKSArIHNjYWxlX3hfbG9nMTAoKSArIAogIGxhYnModGl0bGUgPSAiQ08yIHBlciBjYXBpdGEgYnkgaW5jb21lIGxldmVsIiwgeSA9ICIiLCBmaWxsID0gIiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKYGBge3J9CmRmX2NvMmdkcCB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwKSB8PiBmaWx0ZXIocmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4gCiAgZHJvcF9uYShjbzJwY2FwKSB8PiBmaWx0ZXIoY28ycGNhcCA+IDApIHw+IAogIGdncGxvdChhZXMoY28ycGNhcCwgcmVnaW9uLCBmaWxsID0gcmVnaW9uKSkgKyAKICBnZW9tX2JveHBsb3QoKSArIHNjYWxlX3hfbG9nMTAoKSArIAogIGxhYnModGl0bGUgPSAiQ08yIHBlciBjYXBpdGEgYnkgcmVnaW9uIiwgeSA9ICIiLCBmaWxsID0gIiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKIyMjIyBHRFAgcGVyIGNhcGl0YQoKYGBge3J9CmRmX2NvMmdkcCB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwKSB8PiBmaWx0ZXIocmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4gCiAgZHJvcF9uYShnZHBwY2FwKSB8PiBmaWx0ZXIoaW5jb21lICE9ICJOb3QgY2xhc3NpZmllZCIpIHw+CiAgZ2dwbG90KGFlcyhnZHBwY2FwLCBmaWxsID0gZmFjdG9yKGluY29tZSwgbGV2ZWxzID0gSU5DT01FKSkpICsgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDE1LCBjb2wgPSAiYmxhY2siLCBsaW5ld2lkdGggPSAwLjEpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBHRFAgcGVyIGNhcGl0YSBpbiAyMDIwIiwgZmlsbCA9ICIiKQpgYGAKCmBgYHtyfQpkZl9jbzJnZHAgfD4gZmlsdGVyKHllYXIgJWluJSBjKDE5OTAsIDIwMDAsIDIwMTAsIDIwMjApKSB8PiBmaWx0ZXIocmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4gCiAgZHJvcF9uYShnZHBwY2FwKSB8PiBmaWx0ZXIoZ2RwcGNhcCA+IDApIHw+IGZpbHRlcihpbmNvbWUgIT0gIk5vdCBjbGFzc2lmaWVkIikgfD4gCiAgZ2dwbG90KGFlcyhnZHBwY2FwLCBmaWxsID0gZmFjdG9yKHllYXIpKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMTUsIGNvbCA9ICJibGFjayIsIGxpbmV3aWR0aCA9IDAuMSkgKyAKICBzY2FsZV94X2xvZzEwKCkgKyBmYWNldF93cmFwKH55ZWFyKSArCiAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gb2YgR0RQIHBlciBjYXBpdGEgaW4gMTk5MCwgMjAwMCwgMjAxMCwgMjAyMCIsIGZpbGwgPSAiIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpgYGB7cn0KZGZfY28yZ2RwIHw+IGZpbHRlcih5ZWFyICVpbiUgYygxOTkwLCAyMDAwLCAyMDEwLCAyMDIwKSkgfD4gZmlsdGVyKHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoZ2RwcGNhcCkgfD4gZmlsdGVyKGdkcHBjYXAgPiAwKSB8PiBmaWx0ZXIoaW5jb21lICE9ICJOb3QgY2xhc3NpZmllZCIpIHw+IAogIGdncGxvdChhZXMoZ2RwcGNhcCwgZmFjdG9yKHllYXIpLCBmaWxsID0gZmFjdG9yKHllYXIpKSkgKyAKICBnZW9tX2JveHBsb3QoKSArIHNjYWxlX3hfbG9nMTAoKSArIGxhYnMoeSA9ICIiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpgYGB7cn0KZGZfY28yZ2RwIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PiAKICBkcm9wX25hKGdkcHBjYXApIHw+IGZpbHRlcihnZHBwY2FwID4gMCkgfD4gZmlsdGVyKGluY29tZSAhPSAiTm90IGNsYXNzaWZpZWQiKSB8PiAKICBnZ3Bsb3QoYWVzKGdkcHBjYXAsIGZhY3RvcihpbmNvbWUsIGxldmVscyA9IElOQ09NRSksIGZpbGwgPSBpbmNvbWUpKSArIAogIGdlb21fYm94cGxvdCgpICsgc2NhbGVfeF9sb2cxMCgpICsgCiAgbGFicyh0aXRsZSA9ICJHRFAgcGVyIGNhcGl0YSBieSBpbmNvbWUgbGV2ZWwiLCB5ID0gIiIsIGZpbGwgPSAiIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpgYGB7cn0KZGZfY28yZ2RwIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PiAKICBkcm9wX25hKGdkcHBjYXApIHw+IGZpbHRlcihnZHBwY2FwID4gMCkgfD4gCiAgZ2dwbG90KGFlcyhnZHBwY2FwLCByZWdpb24sIGZpbGwgPSByZWdpb24pKSArIAogIGdlb21fYm94cGxvdCgpICsgc2NhbGVfeF9sb2cxMCgpICsgCiAgbGFicyh0aXRsZSA9ICJHRFAgcGVyIGNhcGl0YSBieSByZWdpb24iLCB5ID0gIiIsIGZpbGwgPSAiIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgojIyMgU2NhdHRlcnBsb3QgZm9yIENvdmFyaWF0aW9uCgojIyMjIFNjYXR0ZXJwbG90IHdpdGggYSByZWdyZXNzaW9uIGxpbmUKCmBgYHtyfQpkZl9jbzJnZHAgfD4gZmlsdGVyKHllYXIgPT0gMjAyMCkgfD4gCiAgZHJvcF9uYShnZHBwY2FwLCBjbzJwY2FwKSB8PgogIGdncGxvdChhZXMoZ2RwcGNhcCwgY28ycGNhcCkpICsgZ2VvbV9wb2ludChhZXMoY29sID0gcmVnaW9uKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSAneX54Jywgc2UgPSBGQUxTRSkgKwogIHNjYWxlX3hfbG9nMTAoKSArIHNjYWxlX3lfbG9nMTAoKSArCiAgbGFicyh0aXRsZSA9ICJHRFAgcGVyIGNhcGl0YSB2cyBDTzIgcGVyIGNhcGl0YSIsCiAgICAgICB4ID0gIkdEUCBwZXIgY2FwaXRhIiwKICAgICAgIHkgPSBleHByZXNzaW9uKHBhc3RlKENPWzJdLCAiIHBlciBjYXBpdGEgaW4gdG9ucyIpKSkKYGBgCgojIyMjIFN1bW1hcnkgb2YgYSBsaW5lYXIgbW9kZWwKCmBgYHtyfQpkZl9jbzJnZHAgfD4gZmlsdGVyKHllYXIgPT0gMjAyMCkgfD4gZHJvcF9uYShnZHBwY2FwLCBjbzJwY2FwKSB8PgogIGxtKGxvZzEwKGNvMnBjYXApfmxvZzEwKGdkcHBjYXApLCBkYXRhID0gXykgfD4gc3VtbWFyeSgpCmBgYAoKIyMgU2Nob29sIEVucm9sbG1lbnQgdnMgR0RQIFBlciBDYXBpdGEKCiMjIyBJbmRleCBTZWFyY2gKCmBgYHtyfQpXRElzZWFyY2goc3RyaW5nID0gInNjaG9vbCBlbnJvbGxtZW50LiooJSBncm9zcykiLCBmaWVsZCA9ICJuYW1lIiwgc2hvcnQgPSBGQUxTRSkKYGBgCgoxLiAgU2Nob29sIGVucm9sbG1lbnQsIHNlY29uZGFyeSAoJSBncm9zcyk6IFNFLlNFQy5FTlJSCgotICAgU2Nob29sIGVucm9sbG1lbnQsIHNlY29uZGFyeSAoJSBncm9zcykgR3Jvc3MgZW5yb2xsbWVudCByYXRpbyBpcyB0aGUgcmF0aW8gb2YgdG90YWwgZW5yb2xsbWVudCwgcmVnYXJkbGVzcyBvZiBhZ2UsIHRvIHRoZSBwb3B1bGF0aW9uIG9mIHRoZSBhZ2UgZ3JvdXAgdGhhdCBvZmZpY2lhbGx5IGNvcnJlc3BvbmRzIHRvIHRoZSBsZXZlbCBvZiBlZHVjYXRpb24gc2hvd24uIFNlY29uZGFyeSBlZHVjYXRpb24gY29tcGxldGVzIHRoZSBwcm92aXNpb24gb2YgYmFzaWMgZWR1Y2F0aW9uIHRoYXQgYmVnYW4gYXQgdGhlIHByaW1hcnkgbGV2ZWwsIGFuZCBhaW1zIGF0IGxheWluZyB0aGUgZm91bmRhdGlvbnMgZm9yIGxpZmVsb25nIGxlYXJuaW5nIGFuZCBodW1hbiBkZXZlbG9wbWVudCwgYnkgb2ZmZXJpbmcgbW9yZSBzdWJqZWN0LSBvciBza2lsbC1vcmllbnRlZCBpbnN0cnVjdGlvbiB1c2luZyBtb3JlIHNwZWNpYWxpemVkIHRlYWNoZXJzLiBTRS5TRUMuRU5SUgoKMi4gIFNjaG9vbCBlbnJvbGxtZW50LCB0ZXJ0aWFyeSAoJSBncm9zcyk6IFNFLlRFUi5FTlJSCgotICAgR3Jvc3MgZW5yb2xsbWVudCByYXRpbyBpcyB0aGUgcmF0aW8gb2YgdG90YWwgZW5yb2xsbWVudCwgcmVnYXJkbGVzcyBvZiBhZ2UsIHRvIHRoZSBwb3B1bGF0aW9uIG9mIHRoZSBhZ2UgZ3JvdXAgdGhhdCBvZmZpY2lhbGx5IGNvcnJlc3BvbmRzIHRvIHRoZSBsZXZlbCBvZiBlZHVjYXRpb24gc2hvd24uIFRlcnRpYXJ5IGVkdWNhdGlvbiwgd2hldGhlciBvciBub3QgdG8gYW4gYWR2YW5jZWQgcmVzZWFyY2ggcXVhbGlmaWNhdGlvbiwgbm9ybWFsbHkgcmVxdWlyZXMsIGFzIGEgbWluaW11bSBjb25kaXRpb24gb2YgYWRtaXNzaW9uLCB0aGUgc3VjY2Vzc2Z1bCBjb21wbGV0aW9uIG9mIGVkdWNhdGlvbiBhdCB0aGUgc2Vjb25kYXJ5IGxldmVsLgoKMy4gIEdEUCBwZXIgY2FwaXRhLCBQUFAgKGNvbnN0YW50IDIwMTcgaW50ZXJuYXRpb25hbCBcJCk6IE5ZLkdEUC5QQ0FQLlBQLktECgotICAgR0RQIHBlciBjYXBpdGEsIFBQUCAoY29uc3RhbnQgMjAxNyBpbnRlcm5hdGlvbmFsIFwkKSBHRFAgcGVyIGNhcGl0YSBiYXNlZCBvbiBwdXJjaGFzaW5nIHBvd2VyIHBhcml0eSAoUFBQKS4gUFBQIEdEUCBpcyBncm9zcyBkb21lc3RpYyBwcm9kdWN0IGNvbnZlcnRlZCB0byBpbnRlcm5hdGlvbmFsIGRvbGxhcnMgdXNpbmcgcHVyY2hhc2luZyBwb3dlciBwYXJpdHkgcmF0ZXMuIEFuIGludGVybmF0aW9uYWwgZG9sbGFyIGhhcyB0aGUgc2FtZSBwdXJjaGFzaW5nIHBvd2VyIG92ZXIgR0RQIGFzIHRoZSBVLlMuIGRvbGxhciBoYXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMuIEdEUCBhdCBwdXJjaGFzZXIncyBwcmljZXMgaXMgdGhlIHN1bSBvZiBncm9zcyB2YWx1ZSBhZGRlZCBieSBhbGwgcmVzaWRlbnQgcHJvZHVjZXJzIGluIHRoZSBjb3VudHJ5IHBsdXMgYW55IHByb2R1Y3QgdGF4ZXMgYW5kIG1pbnVzIGFueSBzdWJzaWRpZXMgbm90IGluY2x1ZGVkIGluIHRoZSB2YWx1ZSBvZiB0aGUgcHJvZHVjdHMuIEl0IGlzIGNhbGN1bGF0ZWQgd2l0aG91dCBtYWtpbmcgZGVkdWN0aW9ucyBmb3IgZGVwcmVjaWF0aW9uIG9mIGZhYnJpY2F0ZWQgYXNzZXRzIG9yIGZvciBkZXBsZXRpb24gYW5kIGRlZ3JhZGF0aW9uIG9mIG5hdHVyYWwgcmVzb3VyY2VzLiBEYXRhIGFyZSBpbiBjb25zdGFudCAyMDE3IGludGVybmF0aW9uYWwgZG9sbGFycy4gSUQ6IE5ZLkdEUC5QQ0FQLlBQLktECgojIyMgSW1wb3J0aW5nIERhdGEKCmBgYHtyIGNhY2hlID0gVFJVRX0KZGZfc2VjX3Rlcl9nZHAgPC0gV0RJKGluZGljYXRvciA9IGMoc2VjID0gIlNFLlNFQy5FTlJSIiwgdGVyID0gIlNFLlRFUi5FTlJSIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdkcHBjYXAgPSAiTlkuR0RQLlBDQVAuUFAuS0QiKSwgZXh0cmEgPSBUUlVFKQpgYGAKCmBgYHtyfQp3cml0ZV9jc3YoZGZfc2VjZ2RwLCAiZGF0YS9zZWNfdGVyX2dkcC5jc3YiKQpgYGAKCmBgYHtyfQpkZl9zZWNnZHAgPC0gcmVhZF9jc3YoImRhdGEvc2VjX3Rlcl9nZHAuY3N2IikKYGBgCgojIyMgVmlzdWFsaXphdGlvbiBieSBMaW5lIEdyYXBocwoKYGBge3J9CkNPVU5UUlkgPC0gIldvcmxkIgpkZl9zZWNfdGVyX2dkcCB8PiBmaWx0ZXIoY291bnRyeSA9PSBDT1VOVFJZKSB8PiBkcm9wX25hKHNlYywgdGVyKSB8PgogIGdncGxvdCgpICsgZ2VvbV9saW5lKGFlcyh5ZWFyLCBzZWMpLCBjb2wgPSAiYmx1ZSIpICsgZ2VvbV9saW5lKGFlcyh5ZWFyLCB0ZXIpLCBjb2wgPSAicmVkIikgKwogIGxhYnModGl0bGUgPSAiU2Nob29sIGVucm9sbG1lbnQ7IFNlY29uZGFyeSBhbmQgVGVydGlhcnkiLCAKICAgICAgIHN1YnRpdGxlID0gInNlY29uZGFyeSBpbiBibHVlIGFuZCB0ZXJ0aWFyeSBpbiByZWQiLCB5ID0gIiIpCmBgYAoKYGBge3J9CklOQ09NRSA8LSBjKCJMb3cgaW5jb21lIiwgIkxvdyAmIG1pZGRsZSBpbmNvbWUiLCAiTG93ZXIgbWlkZGxlIGluY29tZSIsICJNaWRkbGUgaW5jb21lIiwgIlVwcGVyIG1pZGRsZSBpbmNvbWUiLCAiSGlnaCBpbmNvbWUiKQpkZl9zZWNfdGVyX2dkcCB8PiBmaWx0ZXIoY291bnRyeSAlaW4lIElOQ09NRSkgfD4gZHJvcF9uYShzZWMsIHRlcikgfD4KICBnZ3Bsb3QoYWVzKGxpbmV0eXBlID0gZmFjdG9yKGNvdW50cnksIGxldmVscyA9IElOQ09NRSkpKSArIGdlb21fbGluZShhZXMoeWVhciwgc2VjKSwgY29sID0gImJsdWUiKSArIGdlb21fbGluZShhZXMoeWVhciwgdGVyKSwgY29sID0gInJlZCIpICsgeWxpbShjKDAsMTEwKSkgKwogIGxhYnModGl0bGUgPSAiU2Nob29sIGVucm9sbG1lbnQ7IFNlY29uZGFyeSBhbmQgVGVydGlhcnkiLCAKICAgICAgIHN1YnRpdGxlID0gInNlY29uZGFyeSBpbiBibHVlIGFuZCB0ZXJ0aWFyeSBpbiByZWQiLCBsaW5ldHlwZSA9ICJJbmNvbWUgTGV2ZWxzIiwgeSA9ICIiKQpgYGAKCiMjIyBTY2F0dGVycGxvdCBmb3IgQ292YXJpYXRpb24KCmBgYHtyfQpkZl9zZWNfdGVyX2dkcCB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwKSB8PiBkcm9wX25hKHNlYywgdGVyLCBnZHBwY2FwKSB8PgogIGdncGxvdCgpICsgZ2VvbV9wb2ludChhZXMoZ2RwcGNhcCwgc2VjKSwgY29sID0gImJsdWUiKSArIAogIGdlb21fcG9pbnQoYWVzKGdkcHBjYXAsIHRlciksIGNvbCA9ICJyZWQiKSArCiAgbGFicyh0aXRsZSA9ICJTY2hvb2wgZW5yb2xsbWVudDsgU2Vjb25kYXJ5IGFuZCBUZXJ0aWFyeSB2cyBHRFAgcGVyIGNhcGl0YSIsIAogICAgICAgc3VidGl0bGUgPSAic2Vjb25kYXJ5IGluIGJsdWUgYW5kIHRlcnRpYXJ5IGluIHJlZCIsIHkgPSAiIikKYGBgCgpgYGB7cn0KZGZfc2VjX3Rlcl9nZHAgfD4gZmlsdGVyKHllYXIgPT0gMjAyMCkgfD4gZHJvcF9uYShzZWMsIHRlciwgZ2RwcGNhcCkgfD4KICBnZ3Bsb3QoKSArIGdlb21fcG9pbnQoYWVzKGdkcHBjYXAsIHNlYyksIGNvbCA9ICJibHVlIikgKyAKICBnZW9tX3BvaW50KGFlcyhnZHBwY2FwLCB0ZXIpLCBjb2wgPSAicmVkIikgKyAKICBzY2FsZV94X2xvZzEwKCkgKwogIGxhYnModGl0bGUgPSAiU2Nob29sIGVucm9sbG1lbnQ7IFNlY29uZGFyeSBhbmQgVGVydGlhcnkgdnMgR0RQIHBlciBjYXBpdGEgaW4gbG9nMTAgc2NhbGUiLCAKICAgICAgIHN1YnRpdGxlID0gInNlY29uZGFyeSBpbiBibHVlIGFuZCB0ZXJ0aWFyeSBpbiByZWQiLCB5ID0gIiIpCmBgYAoKYGBge3J9CmRmX3NlY190ZXJfZ2RwIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGRyb3BfbmEoc2VjLCB0ZXIsIGdkcHBjYXApIHw+CiAgZ2dwbG90KCkgKyBnZW9tX3BvaW50KGFlcyhnZHBwY2FwLCBzZWMpLCBjb2wgPSAiYmx1ZSIpICsgCiAgZ2VvbV9wb2ludChhZXMoZ2RwcGNhcCwgdGVyKSwgY29sID0gInJlZCIpICsKICBnZW9tX3Ntb290aChhZXMoZ2RwcGNhcCwgc2VjKSwgY29sID0gImJsdWUiLCBtZXRob2QgPSAibG0iLCBmb3JtdWxhID0gJ3l+eCcsIHNlID0gRkFMU0UpICsKICBnZW9tX3Ntb290aChhZXMoZ2RwcGNhcCwgdGVyKSwgY29sID0gInJlZCIsIG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSAneX54Jywgc2UgPSBGQUxTRSkgKwogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh0aXRsZSA9ICJTY2hvb2wgZW5yb2xsbWVudDsgU2Vjb25kYXJ5IGFuZCBUZXJ0aWFyeSB2cyBHRFAgcGVyIGNhcGl0YSBpbiBsb2cxMCBzY2FsZSIsIAogICAgICAgc3VidGl0bGUgPSAic2Vjb25kYXJ5IGluIGJsdWUgYW5kIHRlcnRpYXJ5IGluIHJlZCB3aXRoIHJlZ3Jlc3Npb24gbGluZXMiLCB5ID0gIiIpCmBgYAoKYGBge3J9CmRmX3NlY190ZXJfZ2RwIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGRyb3BfbmEoZ2RwcGNhcCwgc2VjKSB8PgogIGxtKHNlY35sb2cxMChnZHBwY2FwKSwgZGF0YSA9IF8pIHw+IHN1bW1hcnkoKQpgYGAKCmBgYHtyfQpkZl9zZWNfdGVyX2dkcCB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwKSB8PiBkcm9wX25hKGdkcHBjYXAsIHRlcikgfD4KICBsbSh0ZXJ+bG9nMTAoZ2RwcGNhcCksIGRhdGEgPSBfKSB8PiBzdW1tYXJ5KCkKYGBgCgpgYGB7cn0KZGZfc2VjX3Rlcl9nZHAgfD4gZmlsdGVyKHllYXIgPT0gMjAyMCwgcmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4gZHJvcF9uYShzZWMsIHJlZ2lvbikgfD4KICBnZ3Bsb3QoYWVzKHNlYywgcmVnaW9uLCBmaWxsID0gcmVnaW9uKSkgKyBnZW9tX2JveHBsb3QoKSArIAogIGxhYnMoeCA9ICJTY2hvb2wgZW5yb2xsbWVudCwgc2Vjb25kYXJ5ICglIGdyb3NzKSIsIHkgPSAiIikgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKYGBge3J9CmRmX3NlY190ZXJfZ2RwIHw+IGZpbHRlcih5ZWFyID09IDIwMjAsIGluY29tZSAhPSJBZ2dyZWdhdGVzIikgfD4gZHJvcF9uYShzZWMsIGluY29tZSkgfD4KICBnZ3Bsb3QoYWVzKHNlYywgZmFjdG9yKGluY29tZSwgbGV2ZWxzID0gSU5DT01FKSwgZmlsbCA9IGluY29tZSkpICsgZ2VvbV9ib3hwbG90KCkgKyAKICBsYWJzKHRpdGxlID0gIlNlY29uYXJ5IGVkdWNhdGlvbjogU2Nob29sIGVucm9sbG1lbnQgYnkgaW5jb21lIGxldmVsIiwgeCA9ICJTY2hvb2wgZW5yb2xsbWVudCwgc2Vjb25kYXJ5ICglIGdyb3NzKSIsIHkgPSAiIikgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKYGBge3J9CmRmX3NlY190ZXJfZ2RwIHw+IGZpbHRlcih5ZWFyID09IDIwMjAsIHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+IGRyb3BfbmEodGVyLCByZWdpb24pIHw+CiAgZ2dwbG90KGFlcyh0ZXIsIHJlZ2lvbiwgZmlsbCA9IHJlZ2lvbikpICsgZ2VvbV9ib3hwbG90KCkgKyAKICBsYWJzKHggPSAiU2Nob29sIGVucm9sbG1lbnQsIHRlcnRpYXJ5ICglIGdyb3NzKSIsIHkgPSAiIikgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKYGBge3J9CmRmX3NlY190ZXJfZ2RwIHw+IGZpbHRlcih5ZWFyID09IDIwMjAsIGluY29tZSAhPSAiQWdncmVnYXRlcyIpIHw+IGRyb3BfbmEodGVyLCBpbmNvbWUpIHw+CiAgZ2dwbG90KGFlcyh0ZXIsIGZhY3RvcihpbmNvbWUsIGxldmVscyA9IElOQ09NRSksIGZpbGwgPSBpbmNvbWUpKSArIGdlb21fYm94cGxvdCgpICsgCiAgbGFicyh0aXRsZSA9ICJUZXJ0aWFyeSBlZHVjYXRpb246IFNjaG9vbCBlbnJvbGxtZW50IGJ5IGluY29tZSBsZXZlbCIsIHggPSAiU2Nob29sIGVucm9sbG1lbnQsIHRlcnRpYXJ5ICglIGdyb3NzKSIsIHkgPSAiIikgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKKipPYnNlcnZhdGlvbnMqKgoKLSAgIEluY29tZSBsZXZlbCBoYXMgbW9yZSBlZmZlY3Qgb24gc2Nob29sIGVucm9sbG1lbnQgdG8gdGVydGlhcnkgZWR1Y2F0aW9uCgojIFlvdXIgUHJvamVjdAoKIyMgVGl0bGUgb2YgeW91ciBwcm9qZWN0CgpXZSBzdHVkeSAuLi4uLgoKMS4gIE5hbWUgb2YgdGhlIGluZGljYXRvciAxOiBJbmRpY2F0b3IgQ29kZSAxCgotICAgRGVzY3JpcHRpb246CgoyLiAgTmFtZSBvZiB0aGUgaW5kaWNhdG9yIDI6IEluZGljYXRvciBDb2RlIDIKCi0gICBEZXNjcmlwdGlvbjoKCiMjIyBJbXBvcnRpbmcgRGF0YQoKYGBgez1odG1sfQo8c3BhbiBzdHlsZSA9ICJjb2xvcjogcmVkOyI+RWRpdCB0aGUgZm9sbG93aW5nIGNvZGUgY2h1bmshPC9zcGFuPgpgYGAKYGBge3J9CmNob3Nlbl9pbmRpY2F0b3JfMSA8LSAiRU4uQVRNLkNPMkUuUEMiCnNob3J0X25hbWVfMSA8LSAiY28ycGNhcCIKY2hvc2VuX2luZGljYXRvcl8yIDwtICJOWS5HRFAuUENBUC5QUC5LRCIKc2hvcnRfbmFtZV8yIDwtICJnZHBwY2FwIgpgYGAKCmBgYHtyIGNhY2hlID0gVFJVRX0KZGZfeW91cmRhdGEgPC0gV0RJKGluZGljYXRvciA9IGMoc2hvcnRfbmFtZV8xID0gY2hvc2VuX2luZGljYXRvcl8xLCBzaG9ydF9uYW1lXzIgPSBjaG9zZW5faW5kaWNhdG9yXzIpLAogICAgICAgICAgICAgICAgIGV4dHJhID0gVFJVRSkKYGBgCgpgYGB7cn0Kd3JpdGVfY3N2KGRmX3lvdXJkYXRhLCAiZGF0YS95b3VyZGF0YS5jc3YiKQpgYGAKCmBgYHtyfQpkZl95b3VyZGF0YSA8LSByZWFkX2NzdigiZGF0YS95b3VyZGF0YS5jc3YiKQpgYGAKCiMjIyBWaXN1YWxpemF0aW9uIGJ5IExpbmUgR3JhcGhzCgojIyMjIE5hbWUgb2YgdGhlIEluZGljYXRvciAxCgpgYGB7PWh0bWx9CjxzcGFuIHN0eWxlID0gImNvbG9yOiByZWQ7Ij5FZGl0IHRoZSB0aXRsZSBhbmQgdGhlIGxhYmVsIG9mIHktYXhpcy48L3NwYW4+CmBgYApgYGB7cn0KQ09VTlRSWSA8LSAiV29ybGQiCmRmX3lvdXJkYXRhIHw+IGZpbHRlcihjb3VudHJ5ID09IENPVU5UUlkpIHw+IGRyb3BfbmEoc2hvcnRfbmFtZV8xKSB8PgogIGdncGxvdChhZXMoeWVhciwgc2hvcnRfbmFtZV8xKSkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9ICIiLAogICAgICAgeSA9ICIiKQpgYGAKCioqT2JzZXJ2YXRpb25zIGFuZCBRdWVzdGlvbnM6KioKCi0gICAKCmBgYHs9aHRtbH0KPHNwYW4gc3R5bGUgPSAiY29sb3I6IHJlZDsiPkVkaXQgSVNPMkMsIHRpdGxlLCBzdWJ0aXRsZSwgYW5kIHRoZSBsYWJlbCBvZiB5LWF4aXMuPC9zcGFuPgpgYGAKYGBge3J9CklTTzJDIDwtIGMoIkpQIiwgIkNOIiwgIklEIiwgIkdCIiwgIlVTIiwgIkRFIiwgIkZSIikKZGZfeW91cmRhdGEgfD4gZmlsdGVyKGlzbzJjICVpbiUgSVNPMkMpIHw+IGRyb3BfbmEoc2hvcnRfbmFtZV8xKSB8PgogIGdncGxvdChhZXMoeWVhciwgc2hvcnRfbmFtZV8xLCBjb2wgPSBpc28yYykpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiIiwKICAgICAgIHN1YnRpdGxlID0gIkNoaW5hLCBHZXJtYW55LCBGcmFuY2UsIFVuaXRlZCBLaW5nZG9tLCBJbmRpYSwgSmFwYW4sIFVuaXRlZCBTdGF0ZXMiLCAKICAgICAgIHkgPSAiIikKYGBgCgoqKk9ic2VydmF0aW9ucyBhbmQgUXVlc3Rpb25zOioqCgotICAgCgojIyMjIE5hbWUgb2YgdGhlIEluZGljYXRvciAyCgpgYGB7PWh0bWx9CjxzcGFuIHN0eWxlID0gImNvbG9yOiByZWQ7Ij5FZGl0IENPVU5UUlkgYW5kIHRoZSB0aXRsZS48L3NwYW4+CmBgYApgYGB7cn0KQ09VTlRSWSA8LSAiV29ybGQiCmRmX3lvdXJkYXRhIHw+IGZpbHRlcihjb3VudHJ5ID09IENPVU5UUlkpIHw+IGRyb3BfbmEoc2hvcnRfbmFtZV8yKSB8PgogIGdncGxvdChhZXMoeWVhciwgc2hvcnRfbmFtZV8yKSkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9ICIiKQpgYGAKCioqT2JzZXJ2YXRpb25zIGFuZCBRdWVzdGlvbnM6KioKCi0gICAKCmBgYHs9aHRtbH0KPHNwYW4gc3R5bGUgPSAiY29sb3I6IHJlZDsiPkVkaXQgSVNPMkMsIHRpdGxlLCBzdWJ0aXRsZSwgYW5kIHRoZSBsYWJlbCBvZiB5LWF4aXMsIGFuZCBhZGQgY2FwdGlvbiBpZiBwcmVmZXJhYmxlLjwvc3Bhbj4KYGBgCmBgYHtyfQpJU08yQyA8LSBjKCJKUCIsICJDTiIsICJJRCIsICJHQiIsICJVUyIsICJERSIsICJGUiIpCmRmX3lvdXJkYXRhIHw+IGZpbHRlcihpc28yYyAlaW4lIElTTzJDKSB8PiBkcm9wX25hKHNob3J0X25hbWVfMikgfD4KICBnZ3Bsb3QoYWVzKHllYXIsIHNob3J0X25hbWVfMiwgY29sID0gaXNvMmMpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gIiIsCiAgICAgICBzdWJ0aXRsZSA9ICJDaGluYSwgR2VybWFueSwgRnJhbmNlLCBVbml0ZWQgS2luZ2RvbSwgSW5kaWEsIEphcGFuLCBVbml0ZWQgU3RhdGVzIiwgCiAgICAgICB5ID0gIiIsCiAgICAgICBjYXB0aW9uID0gIiIpCmBgYAoKKipPYnNlcnZhdGlvbnMgYW5kIFF1ZXN0aW9uczoqKgoKLSAgIAoKIyMjIyBSYW5raW5nIG9mIHRoZSBpbmRpY2F0b3IgMQoKYGBgez1odG1sfQo8c3BhbiBzdHlsZSA9ICJjb2xvcjogcmVkOyI+RWRpdCB5ZWFyIGlmIG5lY2Vzc2FyeS48L3NwYW4+CmBgYApgYGB7cn0KZGZfeW91cmRhdGEgfD4gZmlsdGVyKHllYXIgPT0gMjAyMCkgfD4gZmlsdGVyKHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+CiAgZHJvcF9uYShzaG9ydF9uYW1lXzEpIHw+IGFycmFuZ2UoZGVzYyhzaG9ydF9uYW1lXzEpKQpgYGAKCmBgYHtyfQpkZl95b3VyZGF0YSB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwKSB8PiBmaWx0ZXIocmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4KICBkcm9wX25hKHNob3J0X25hbWVfMSkgfD4gYXJyYW5nZShzaG9ydF9uYW1lXzEpCmBgYAoKKipPYnNlcnZhdGlvbnMgYW5kIFF1ZXN0aW9uczoqKgoKLSAgIAoKIyMjIyBSYW5raW5nIG9mIHRoZSBJbmRpY2F0b3IgMgoKYGBge3J9CmRmX3lvdXJkYXRhIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PgogIGRyb3BfbmEoc2hvcnRfbmFtZV8yKSB8PiBhcnJhbmdlKGRlc2Moc2hvcnRfbmFtZV8yKSkKYGBgCgoqKk9ic2VydmF0aW9ucyBhbmQgUXVlc3Rpb25zOioqCgotICAgCgpgYGB7cn0KZGZfeW91cmRhdGEgfD4gZmlsdGVyKHllYXIgPT0gMjAyMCkgfD4gZmlsdGVyKHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+CiAgZHJvcF9uYShzaG9ydF9uYW1lXzIpIHw+IGFycmFuZ2Uoc2hvcnRfbmFtZV8yKQpgYGAKCioqT2JzZXJ2YXRpb25zIGFuZCBRdWVzdGlvbnM6KioKCi0gICAKCiMjIyBIaXN0b2dyYW1zIGFuZCBCb3hwbG90cyBmb3IgVmFyaWF0aW9uCgojIyMjIE5hbWUgb2YgdGhlIEluZGljYXRvciAxCgpgYGB7PWh0bWx9CjxzcGFuIHN0eWxlID0gImNvbG9yOiByZWQ7Ij5FZGl0IHRoZSB0aXRsZSBhbmQgeWVhci48L3NwYW4+CmBgYApgYGB7cn0KZGZfeW91cmRhdGEgfD4gZmlsdGVyKHllYXIgPT0gMjAyMCkgfD4gZmlsdGVyKHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoc2hvcnRfbmFtZV8xKSB8PiBmaWx0ZXIoaW5jb21lICE9ICJOb3QgY2xhc3NpZmllZCIpIHw+CiAgZ2dwbG90KGFlcyhzaG9ydF9uYW1lXzEsIGZpbGwgPSBmYWN0b3IoaW5jb21lLCBsZXZlbHMgPSBJTkNPTUUpKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMTUsIGNvbCA9ICJibGFjayIsIGxpbmV3aWR0aCA9IDAuMSkgKyAKICBzY2FsZV94X2xvZzEwKCkgKwogIGxhYnModGl0bGUgPSAiIiwgZmlsbCA9ICIiKQpgYGAKCioqT2JzZXJ2YXRpb25zIGFuZCBRdWVzdGlvbnM6KioKCi0gICAKCmBgYHs9aHRtbH0KPHNwYW4gc3R5bGUgPSAiY29sb3I6IHJlZDsiPkVkaXQgdGhlIHRpdGxlIGFuZCB0aGUgeWVhcnMuPC9zcGFuPgpgYGAKYGBge3J9CmRmX3lvdXJkYXRhIHw+IGZpbHRlcih5ZWFyICVpbiUgYygxOTkwLCAyMDAwLCAyMDEwLCAyMDIwKSkgfD4gZmlsdGVyKHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoc2hvcnRfbmFtZV8xKSB8PiBmaWx0ZXIoc2hvcnRfbmFtZV8xID4gMCkgfD4gZmlsdGVyKGluY29tZSAhPSAiTm90IGNsYXNzaWZpZWQiKSB8PiAKICBnZ3Bsb3QoYWVzKHNob3J0X25hbWVfMSwgZmlsbCA9IGZhY3Rvcih5ZWFyKSkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDE1LCBjb2wgPSAiYmxhY2siLCBsaW5ld2lkdGggPSAwLjEpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsgZmFjZXRfd3JhcCh+eWVhcikgKwogIGxhYnModGl0bGUgPSAiIiwgZmlsbCA9ICIiKQpgYGAKCioqT2JzZXJ2YXRpb25zIGFuZCBRdWVzdGlvbnM6KioKCi0gICAKCmBgYHtyfQpkZl95b3VyZGF0YSB8PiBmaWx0ZXIoeWVhciAlaW4lIGMoMTk5MCwgMjAwMCwgMjAxMCwgMjAyMCkpIHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PiAKICBkcm9wX25hKHNob3J0X25hbWVfMSkgfD4gZmlsdGVyKHNob3J0X25hbWVfMSA+IDApIHw+IGZpbHRlcihpbmNvbWUgIT0gIk5vdCBjbGFzc2lmaWVkIikgfD4gCiAgZ2dwbG90KGFlcyhzaG9ydF9uYW1lXzEsIGZhY3Rvcih5ZWFyKSwgZmlsbCA9IGZhY3Rvcih5ZWFyKSkpICsgCiAgZ2VvbV9ib3hwbG90KCkgKyBzY2FsZV94X2xvZzEwKCkgKyBsYWJzKHkgPSAiIikgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKKipPYnNlcnZhdGlvbnMgYW5kIFF1ZXN0aW9uczoqKgoKLSAgIAoKYGBgez1odG1sfQo8c3BhbiBzdHlsZSA9ICJjb2xvcjogcmVkOyI+RWRpdCB0aGUgdGl0bGUsIGFuZCB0aGUgeWVhciBpZiBuZWNlc3NhcnkuPC9zcGFuPgpgYGAKYGBge3J9CmRmX3lvdXJkYXRhIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PiAKICBkcm9wX25hKHNob3J0X25hbWVfMSkgfD4gZmlsdGVyKHNob3J0X25hbWVfMSA+IDApIHw+IGZpbHRlcihpbmNvbWUgIT0gIk5vdCBjbGFzc2lmaWVkIikgfD4gCiAgZ2dwbG90KGFlcyhzaG9ydF9uYW1lXzEsIGZhY3RvcihpbmNvbWUsIGxldmVscyA9IElOQ09NRSksIGZpbGwgPSBpbmNvbWUpKSArIAogIGdlb21fYm94cGxvdCgpICsgc2NhbGVfeF9sb2cxMCgpICsgCiAgbGFicyh0aXRsZSA9ICIiLCB5ID0gIiIsIGZpbGwgPSAiIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgoqKk9ic2VydmF0aW9ucyBhbmQgUXVlc3Rpb25zOioqCgotICAgCgpgYGB7PWh0bWx9CjxzcGFuIHN0eWxlID0gImNvbG9yOiByZWQ7Ij5FZGl0IHRoZSB0aXRsZSBhbmQgeWVhciBpZiBuZWNlc3NhcnkuPC9zcGFuPgpgYGAKYGBge3J9CmRmX3lvdXJkYXRhIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PiAKICBkcm9wX25hKHNob3J0X25hbWVfMSkgfD4gZmlsdGVyKHNob3J0X25hbWVfMSA+IDApIHw+IAogIGdncGxvdChhZXMoc2hvcnRfbmFtZV8xLCByZWdpb24sIGZpbGwgPSByZWdpb24pKSArIAogIGdlb21fYm94cGxvdCgpICsgc2NhbGVfeF9sb2cxMCgpICsgCiAgbGFicyh0aXRsZSA9ICIiLCB5ID0gIiIsIGZpbGwgPSAiIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgoqKk9ic2VydmF0aW9ucyBhbmQgUXVlc3Rpb25zOioqCgotICAgCgojIyMjIEdEUCBwZXIgY2FwaXRhCgpgYGB7PWh0bWx9CjxzcGFuIHN0eWxlID0gImNvbG9yOiByZWQ7Ij5FZGl0IHRoZSB0aXRsZSwgYW5kIHllYXIgaWYgbmVjZXNzYXJ5Ljwvc3Bhbj4KYGBgCmBgYHtyfQpkZl95b3VyZGF0YSB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwKSB8PiBmaWx0ZXIocmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4gCiAgZHJvcF9uYShzaG9ydF9uYW1lXzIpIHw+IGZpbHRlcihpbmNvbWUgIT0gIk5vdCBjbGFzc2lmaWVkIikgfD4KICBnZ3Bsb3QoYWVzKHNob3J0X25hbWVfMiwgZmlsbCA9IGZhY3RvcihpbmNvbWUsIGxldmVscyA9IElOQ09NRSkpKSArIGdlb21faGlzdG9ncmFtKGJpbnMgPSAxNSwgY29sID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC4xKSArIAogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh0aXRsZSA9ICIiLCBmaWxsID0gIiIpCmBgYAoKYGBgez1odG1sfQo8c3BhbiBzdHlsZSA9ICJjb2xvcjogcmVkOyI+RWRpdCB0aGUgdGl0bGUgYW5kIHRoZSB5ZWFyIGlmIG5lY2Vzc2FyeS48L3NwYW4+CmBgYApgYGB7cn0KZGZfeW91cmRhdGEgfD4gZmlsdGVyKHllYXIgJWluJSBjKDE5OTAsIDIwMDAsIDIwMTAsIDIwMjApKSB8PiBmaWx0ZXIocmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4gCiAgZHJvcF9uYShzaG9ydF9uYW1lXzIpIHw+IGZpbHRlcihzaG9ydF9uYW1lXzIgPiAwKSB8PiBmaWx0ZXIoaW5jb21lICE9ICJOb3QgY2xhc3NpZmllZCIpIHw+IAogIGdncGxvdChhZXMoc2hvcnRfbmFtZV8yLCBmaWxsID0gZmFjdG9yKHllYXIpKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMTUsIGNvbCA9ICJibGFjayIsIGxpbmV3aWR0aCA9IDAuMSkgKyAKICBzY2FsZV94X2xvZzEwKCkgKyBmYWNldF93cmFwKH55ZWFyKSArCiAgbGFicyh0aXRsZSA9ICIiLCBmaWxsID0gIiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKKipPYnNlcnZhdGlvbnMgYW5kIFF1ZXN0aW9uczoqKgoKLSAgIAoKYGBge3J9CmRmX3lvdXJkYXRhIHw+IGZpbHRlcih5ZWFyICVpbiUgYygxOTkwLCAyMDAwLCAyMDEwLCAyMDIwKSkgfD4gZmlsdGVyKHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoc2hvcnRfbmFtZV8yKSB8PiBmaWx0ZXIoc2hvcnRfbmFtZV8yID4gMCkgfD4gZmlsdGVyKGluY29tZSAhPSAiTm90IGNsYXNzaWZpZWQiKSB8PiAKICBnZ3Bsb3QoYWVzKHNob3J0X25hbWVfMiwgZmFjdG9yKHllYXIpLCBmaWxsID0gZmFjdG9yKHllYXIpKSkgKyAKICBnZW9tX2JveHBsb3QoKSArIHNjYWxlX3hfbG9nMTAoKSArIGxhYnMoeSA9ICIiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgoqKk9ic2VydmF0aW9ucyBhbmQgUXVlc3Rpb25zOioqCgotICAgCgpgYGB7PWh0bWx9CjxzcGFuIHN0eWxlID0gImNvbG9yOiByZWQ7Ij5FZGl0IHRoZSB0aXRsZSwgYW5kIHRoZSB5ZWFyIGlmIG5lY2Vzc2FyeS48L3NwYW4+CmBgYApgYGB7cn0KZGZfeW91cmRhdGEgfD4gZmlsdGVyKHllYXIgPT0gMjAyMCkgfD4gZmlsdGVyKHJlZ2lvbiAhPSAiQWdncmVnYXRlcyIpIHw+IAogIGRyb3BfbmEoc2hvcnRfbmFtZV8yKSB8PiBmaWx0ZXIoc2hvcnRfbmFtZV8yID4gMCkgfD4gZmlsdGVyKGluY29tZSAhPSAiTm90IGNsYXNzaWZpZWQiKSB8PiAKICBnZ3Bsb3QoYWVzKHNob3J0X25hbWVfMiwgZmFjdG9yKGluY29tZSwgbGV2ZWxzID0gSU5DT01FKSwgZmlsbCA9IGluY29tZSkpICsgCiAgZ2VvbV9ib3hwbG90KCkgKyBzY2FsZV94X2xvZzEwKCkgKyAKICBsYWJzKHRpdGxlID0gIiIsIHkgPSAiIiwgZmlsbCA9ICIiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCioqT2JzZXJ2YXRpb25zIGFuZCBRdWVzdGlvbnM6KioKCi0gICAKCmBgYHs9aHRtbH0KPHNwYW4gc3R5bGUgPSAiY29sb3I6IHJlZDsiPkVkaXQgdGhlIHRpdGxlIGFuZCB0aGUgeWVhciBpZiBuZWNlc3NhcnkuPC9zcGFuPgpgYGAKYGBge3J9CmRmX3lvdXJkYXRhIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PiAKICBkcm9wX25hKHNob3J0X25hbWVfMikgfD4gZmlsdGVyKHNob3J0X25hbWVfMiA+IDApIHw+IAogIGdncGxvdChhZXMoc2hvcnRfbmFtZV8yLCByZWdpb24sIGZpbGwgPSByZWdpb24pKSArIAogIGdlb21fYm94cGxvdCgpICsgc2NhbGVfeF9sb2cxMCgpICsgCiAgbGFicyh0aXRsZSA9ICIiLCB5ID0gIiIsIGZpbGwgPSAiIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgojIyMgU2NhdHRlcnBsb3QgZm9yIENvdmFyaWF0aW9uCgojIyMjIFNjYXR0ZXJwbG90IHdpdGggYSByZWdyZXNzaW9uIGxpbmUKCmBgYHs9aHRtbH0KPHNwYW4gc3R5bGUgPSAiY29sb3I6IHJlZDsiPkVkaXQgdGhlIHRpdGxlLCB0aGUgbGFiZWxzIG9mIHgtIGFuZCB5LSBheGVzLjwvc3Bhbj4KYGBgCmBgYHtyfQpkZl95b3VyZGF0YSB8PiBmaWx0ZXIoeWVhciA9PSAyMDIwKSB8PiAKICBkcm9wX25hKHNob3J0X25hbWVfMiwgc2hvcnRfbmFtZV8xKSB8PgogIGdncGxvdChhZXMoc2hvcnRfbmFtZV8yLCBzaG9ydF9uYW1lXzEpKSArIGdlb21fcG9pbnQoYWVzKGNvbCA9IHJlZ2lvbikpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0gJ3l+eCcsIHNlID0gRkFMU0UpICsKICBzY2FsZV94X2xvZzEwKCkgKyBzY2FsZV95X2xvZzEwKCkgKwogIGxhYnModGl0bGUgPSAiIiwKICAgICAgIHggPSAiIiwKICAgICAgIHkgPSAiIikKYGBgCgoqKk9ic2VydmF0aW9ucyBhbmQgUXVlc3Rpb25zOioqCgotICAgCgojIyMjIFN1bW1hcnkgb2YgYSBsaW5lYXIgbW9kZWwKCmBgYHs9aHRtbH0KPHNwYW4gc3R5bGUgPSAiY29sb3I6IHJlZDsiPkVkaXQgeWVhciBpZiBuZWNlc3NhcnkuPC9zcGFuPgpgYGAKYGBge3J9CmRmX3lvdXJkYXRhIHw+IGZpbHRlcih5ZWFyID09IDIwMjApIHw+IGRyb3BfbmEoc2hvcnRfbmFtZV8yLCBzaG9ydF9uYW1lXzEpIHw+CiAgbG0obG9nMTAoc2hvcnRfbmFtZV8xKX5sb2cxMChzaG9ydF9uYW1lXzIpLCBkYXRhID0gXykgfD4gc3VtbWFyeSgpCmBgYAoKKipPYnNlcnZhdGlvbnMgYW5kIFF1ZXN0aW9uczoqKgoKLSAgIAo=